﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.IO;
using System.Text.RegularExpressions;
using ImageScale.Properties;

namespace ImageScale
{
    public partial class FtpFolderBrowserDialog : Form
    {
        private string _ftpUrl = String.Empty;
        public string FtpUrl
        {
            get { return _ftpUrl; }
            set 
            {
                _ftpUrl = value;
                ftpSelectedPath.Text = _ftpUrl;
            }
        }
        public string FtpUser
        {
            get { return ftpUser.Text; }
        }

        public string FtpPassword
        {
            get { return ftpPass.Text; }
        }



        public FtpFolderBrowserDialog()
        {
            InitializeComponent();
        }

        #region Validating controls...
        private void ftpUrl_Validating(object sender, CancelEventArgs e)
        {
            if (String.IsNullOrEmpty(ftpUrl.Text))
            {
                e.Cancel = true;
                return;
            }
            else if (ftpUrl.Text.StartsWith(@"ftp://"))
            {
                ftpUrl.Text = ftpUrl.Text.Substring(6);
            }
            this.FtpUrl = String.Format(@"ftp://{0}", ftpUrl.Text);
        }

        private void ftpUser_Validating(object sender, CancelEventArgs e)
        {
            if (String.IsNullOrEmpty(ftpUser.Text))
            {
                ftpUser.Text = @"anonymous@example.com";
            }
        } 
        #endregion

        private void user_pass_Changed(object sender, EventArgs e)
        {
            if (!String.IsNullOrEmpty(ftpUser.Text))
            {
                connectButton.Enabled = true;
                this.AcceptButton = connectButton;
            }
        }

        private void ftpSelectedPath_TextChanged(object sender, EventArgs e)
        {
            okButton.Enabled = !String.IsNullOrEmpty(ftpSelectedPath.Text);
        }

        private void connectButton_Click(object sender, EventArgs e)
        {
            Uri ftpUri = new Uri(String.Format(@"ftp://{0}", ftpUrl.Text));
            this.AcceptButton = null;
            FtpListDirectories(ftpUri);
            ftpFolders.Focus();
        }

        #region Manage FTP folder list
        private void FtpListDirectories(Uri ftpUri)
        {
            try
            {
                if (ftpUri.Scheme == Uri.UriSchemeFtp)
                {
                    Cursor.Current = Cursors.WaitCursor;
                    FtpWebRequest ftpRequest = FtpWebRequest.Create(ftpUri) as FtpWebRequest;
                    ftpRequest.Method = WebRequestMethods.Ftp.ListDirectoryDetails;
                    ftpRequest.KeepAlive = false;
                    ftpRequest.Credentials = new NetworkCredential(ftpUser.Text, ftpPass.Text);
                    FtpWebResponse ftpResponse = ftpRequest.GetResponse() as FtpWebResponse;
                    if (ftpResponse != null)
                    {
                        string data = String.Empty;
                        using (StreamReader reader = new StreamReader(ftpResponse.GetResponseStream(), Encoding.ASCII))
                        {
                            data = reader.ReadToEnd();
                        }
                        List<FileStruct> files = GetList(data);
                        files.Sort(delegate(FileStruct fs1, FileStruct fs2)
                        {
                            return fs1.Name.CompareTo(fs2.Name);
                        });
                        FillFolderList(files);
                    }
                    Cursor.Current = Cursors.Default;
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, Resources.ERROR, MessageBoxButtons.OK, MessageBoxIcon.Error);
                Cursor.Current = Cursors.Default;
            }
        }

        private void FillFolderList(List<FileStruct> files)
        {
            ftpFolders.Items.Clear();
            ftpFolders.Items.Add(@"[...]", 1);
            foreach (FileStruct file in files)
            {
                if (file.IsDirectory)
                {
                    ListViewItem lvi = new ListViewItem(file.Name);
                    lvi.ImageIndex = 0;
                    lvi.SubItems.Add(String.Format("{0} {1}", file.CreateTime.ToShortDateString(),
                        file.CreateTime.ToShortTimeString()));
                    ftpFolders.Items.Add(lvi);
                }
            }
            ftpFolders.Columns[0].AutoResize(ColumnHeaderAutoResizeStyle.ColumnContent);
            ftpFolders.Columns[1].AutoResize(ColumnHeaderAutoResizeStyle.ColumnContent);
        }

        #region Handle directory list by Adarsh.
        private List<FileStruct> GetList(string datastring)
        {
            List<FileStruct> myListArray = new List<FileStruct>();
            string[] dataRecords = datastring.Split('\n');
            FileListStyle _directoryListStyle = GuessFileListStyle(dataRecords);
            foreach (string s in dataRecords)
            {
                if (_directoryListStyle != FileListStyle.Unknown && s != "")
                {
                    FileStruct f = new FileStruct();
                    f.Name = "..";
                    switch (_directoryListStyle)
                    {
                        case FileListStyle.UnixStyle:
                            f = ParseFileStructFromUnixStyleRecord(s);
                            break;
                        case FileListStyle.WindowsStyle:
                            f = ParseFileStructFromWindowsStyleRecord(s);
                            break;
                    }
                    if (!(f.Name == "." || f.Name == ".."))
                    {
                        myListArray.Add(f);
                    }
                }
            }
            return myListArray;
        }

        private FileStruct ParseFileStructFromWindowsStyleRecord(string Record)
        {
            ///Assuming the record style as 
            /// 02-03-04  07:46PM       <DIR>          Append
            FileStruct f = new FileStruct();
            string processstr = Record.Trim();
            string dateStr = processstr.Substring(0, 8);
            processstr = (processstr.Substring(8, processstr.Length - 8)).Trim();
            string timeStr = processstr.Substring(0, 7);
            processstr = (processstr.Substring(7, processstr.Length - 7)).Trim();
            f.CreateTime = DateTime.Parse(dateStr + " " + timeStr);
            if (processstr.Substring(0, 5) == "<DIR>")
            {
                f.IsDirectory = true;
                processstr = (processstr.Substring(5, processstr.Length - 5)).Trim();
            }
            else
            {
                string[] strs = processstr.Split(new char[] { ' ' });
                processstr = strs[1].Trim();
                f.IsDirectory = false;
            }
            f.Name = processstr;  //Rest is name   
            return f;
        }
        public FileListStyle GuessFileListStyle(string[] recordList)
        {
            foreach (string s in recordList)
            {
                if (s.Length > 10
                 && Regex.IsMatch(s.Substring(0, 10), "(-|d)(-|r)(-|w)(-|x)(-|r)(-|w)(-|x)(-|r)(-|w)(-|x)"))
                {
                    return FileListStyle.UnixStyle;
                }
                else if (s.Length > 8
                 && Regex.IsMatch(s.Substring(0, 8), "[0-9][0-9]-[0-9][0-9]-[0-9][0-9]"))
                {
                    return FileListStyle.WindowsStyle;
                }
            }
            return FileListStyle.Unknown;
        }
        private FileStruct ParseFileStructFromUnixStyleRecord(string Record)
        {
            ///Assuming record style as
            /// dr-xr-xr-x   1 owner    group               0 Nov 25  2002 bussys
            FileStruct f = new FileStruct();
            string processstr = Record.Trim();
            f.Flags = processstr.Substring(0, 9);
            f.IsDirectory = (f.Flags[0] == 'd');
            processstr = (processstr.Substring(11)).Trim();
            _cutSubstringFromStringWithTrim(ref processstr, ' ', 0);   //skip one part
            f.Owner = _cutSubstringFromStringWithTrim(ref processstr, ' ', 0);
            f.Group = _cutSubstringFromStringWithTrim(ref processstr, ' ', 0);
            _cutSubstringFromStringWithTrim(ref processstr, ' ', 0);   //skip one part
            f.CreateTime = DateTime.MinValue;
            DateTime.TryParse(_cutSubstringFromStringWithTrim(ref processstr, ' ', 8), out f.CreateTime);
            f.Name = processstr;   //Rest of the part is name
            return f;
        }
        private string _cutSubstringFromStringWithTrim(ref string s, char c, int startIndex)
        {
            int pos1 = s.IndexOf(c, startIndex);
            string retString = s.Substring(0, pos1);
            s = (s.Substring(pos1)).Trim();
            return retString;
        }
        #endregion

        private void ftpFolders_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (ftpFolders.SelectedItems.Count > 0 && ftpFolders.SelectedIndices[0] > 0)
            {
                ftpSelectedPath.Text = String.Format(@"{0}/{1}", this.FtpUrl, ftpFolders.SelectedItems[0].Text);
            }
        }

        private void ftpFolders_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            if (ftpFolders.SelectedItems.Count > 0)
            {
                ChangeDirectory();
            }
        }

        private void ChangeDirectory()
        {
            if (ftpFolders.SelectedIndices[0] == 0)
            {
                // Go up
                this.FtpUrl = GetParentDirectory(this.FtpUrl);
            }
            else
            {
                this.FtpUrl = ftpSelectedPath.Text;
            }
            FtpListDirectories(new Uri(this.FtpUrl));
            ftpFolders.Items[0].Selected = true;
        }

        private string GetParentDirectory(string path)
        {
            Uri u = new Uri(path);
            int nSegments = u.Segments.Length;
            if (nSegments > 1)
            {
                StringBuilder sb = new StringBuilder(String.Format(@"ftp://{0}", u.Host));
                for (int i = 0; i < nSegments - 1; i++)
                {
                    sb.Append(u.Segments[i]);
                }
                path = sb.ToString();
            }
            return path.TrimEnd(new char[] { '/' });
        }


        private void ftpFolders_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
        {
            if (e.KeyCode == Keys.Enter)
            {
                if (ftpFolders.SelectedItems.Count > 0)
                {
                    ChangeDirectory();
                }
            }
        }
        #endregion


    }

    public struct FileStruct
    {
        public string Flags;
        public string Owner;
        public string Group;
        public bool IsDirectory;
        public DateTime CreateTime;
        public string Name;
    }
    public enum FileListStyle
    {
        UnixStyle,
        WindowsStyle,
        Unknown
    }
}
